$(function () {
    var siteConfig = {
        'user_avatar': '/assets/img/user-avatar.png',
        'chatgpt_avatar': '/assets/img/pull-avatar.png',
        'send_message_url': '/api.php?action=checkMessage',
        'eventsource_url': '/api.php?action=pushMessage',
    }
    var defaults = {
        html: true,        // Enable HTML tags in source
        xhtmlOut: false,        // Use '/' to close single tags (<br />)
        breaks: false,        // Convert '\n' in paragraphs into <br>
        langPrefix: 'language-',  // CSS language prefix for fenced blocks
        linkify: true,         // autoconvert URL-like texts to links
        linkTarget: '',           // set target to open link in
        typographer: true,         // Enable smartypants and other sweet transforms
        _highlight: true,
        _strict: false,
        _view: 'html'
    };
    var contentsArr=[];
    defaults.highlight = function (str, lang) {

        if (!defaults._highlight || !window.hljs) { return ''; }
        var tagReg =/<i[^>]*>([\s\S]*?)<\/i>/;
        var zhanweiReg =/_zhanwei_/;
        str = str.replace(tagReg,"_zhanwei_");
        var hljs = window.hljs;
        if (lang && hljs.getLanguage(lang)) {
            try {
                var value= hljs.highlight(lang, str).value;
                return  value.replace(zhanweiReg,"<i class=\"chat-cursor\"></i>");
            } catch (__) { }
        }

        try {

            var value= hljs.highlightAuto(str).value;
            return  value.replace(zhanweiReg,"<i class=\"chat-cursor\"></i>");
        } catch (__) { }

        return '';
    };
    var mdHtml = new window.Remarkable('full', defaults);
    mdHtml.renderer.rules.table_open = function () {
        return '<table class="table table-striped">\n';
    };
    mdHtml.renderer.rules.paragraph_open = function (tokens, idx) {
        var line;
        if (tokens[idx].lines && tokens[idx].level === 0) {
            line = tokens[idx].lines[0];
            return '<p class="line" data-line="' + line + '">';
        }
        return '<p>';
    };

    mdHtml.renderer.rules.heading_open = function (tokens, idx) {
        var line;
        if (tokens[idx].lines && tokens[idx].level === 0) {
            line = tokens[idx].lines[0];
            return '<h' + tokens[idx].hLevel + ' class="line" data-line="' + line + '">';
        }
        return '<h' + tokens[idx].hLevel + '>';
    };

    /*公用方法*/
    var Api={
        msg:function (msg) {
            layer.msg(msg,{offset: '50px'})
        },
        isIE:function () {
            if (!!window.ActiveXObject || "ActiveXObject" in window){
                return true;
            }else{
                return false;
            }
        },
        isMobile:function () {
            var userAgentInfo = navigator.userAgent;
            var mobileAgents = ['iphone', 'ipod', 'ipad', 'android', 'windows phone', 'blackberry', 'nokia', 'opera mini', 'mobile'];
            var mobile_flag = false;

            //根据userAgent判断是否是手机
            for (var v = 0; v < mobileAgents.length; v++) {
                if (userAgentInfo.indexOf(mobileAgents[v]) > 0) {
                    mobile_flag = true;
                    break;
                }
            }
            var screen_width = window.screen.width;
            var screen_height = window.screen.height;

            //根据屏幕分辨率判断是否是手机
            if (screen_width > 325 && screen_height < 750) {
                mobile_flag = true;
            }
            return mobile_flag;
        },
        createId:function () {
            return new Date().getTime() +Math.floor(Math.random()*4000+1000);
        },
        //发送Ajax请求
        ajax: function (options, success, error) {
            options = typeof options === 'string' ? {"url": options} : options;
            var index;
            if (typeof options.loading === 'undefined' || options.loading) {
                var loadingTxt='';
                if(typeof options.loading === 'undefined'){
                    loadingTxt='请求中请稍后...';
                }else if(typeof options.loading == 'string'){
                    loadingTxt=options.loading;
                }
                index =layer.msg(loadingTxt, {
                    icon: 16,
                    shade: 0.4,
                    time: false //取消自动关闭
                });
            }
            options = $.extend({
                type: "POST",
                dataType: "json",
                xhrFields: {
                    withCredentials: true
                },
                success: function (ret) {
                    index && layer.close(index);
                    ret = Api.events.onAjaxResponse(ret);
                    if (ret.code === 1) {
                        Api.events.onAjaxSuccess(ret, success);
                    } else {
                        Api.events.onAjaxError(ret, error);
                    }
                },
                error: function (xhr) {
                    index && layer.close(index);
                    var ret = {code: xhr.status, msg: xhr.statusText, data: null};
                    Api.events.onAjaxError(ret, error);
                }
            }, options);
            return $.ajax(options);
        },
        setInputStatus:function (display) {
            if(display){
                $('#sendMessage_val').attr('disabled',true)
                $('#sendMessage_btn').attr({'data-loading':1,'disabled':true}).html('<i class="icon icon-spin icon-refresh mr-1"></i>生成中');
            }else{
                $('#sendMessage_val').attr('disabled',false)
                $('#sendMessage_btn').attr({'data-loading':0,'disabled':false}).html('<i class="icon icon-rocket mr-1"></i>发送');
            }
        },
        errorCode:function (errCode,msg,chatItemId) {
            switch (errCode) {
                case "invalid_api_key":
                    msg="API-KEY不合法";
                    break;
                case "context_length_exceeded":
                    msg="问题和上下文长度超限，请重新提问";
                    break;
                case "rate_limit_reached":
                    msg="同时访问用户过多，请稍后再试";
                    break;
                case "access_terminated":
                    msg="违规使用，API-KEY被封禁";
                    break;
                case "no_api_key":
                    msg="未提供API-KEY";
                    break;
                case "insufficient_quota":
                    msg="API-KEY余额不足";
                    break;
                case "account_deactivated":
                    msg="账户已禁用";
                    break;
                case "model_overloaded":
                    msg="OpenAI模型超负荷，请重新发起请求";
                    break;
                case null:
                    msg="OpenAI服务器访问超时或未知类型错误";
                    break;
            }
            Api.updateStreamChatItem(msg,chatItemId);
            Api.setChatMessage({'type':1,message:msg})
            Api.setInputStatus(false)
        },
        //复制
        copyToClipboard:function (text) {
            var input = document.createElement('textarea');
            input.innerHTML = text;
            document.body.appendChild(input);
            input.select();
            var result = document.execCommand('copy');
            document.body.removeChild(input);
            return result;
        },
        //存储会话
        setChatMessage:function (data) {
            var messageArr=$.zui.store.get('chat_message');
            messageArr= typeof messageArr == 'undefined'? [] : messageArr;
            if(messageArr.length > 30){
                messageArr.splice(0,1)
            }
            messageArr.push(data);
            $.zui.store.set('chat_message',messageArr)
        },
        //清空会话
        delChatMessage:function () {
            $.zui.store.remove('chat_message');
            $('#message_chat_content').html('');
            Api.isMeassageTips(0);
        },
        //初始化显示历史消息
        initChatMessage:function () {
            var messageArr=$.zui.store.get('chat_message');
            messageArr= typeof messageArr == 'undefined'? [] : messageArr;
            var domHtml='';
            for (let i=0; i < messageArr.length; i++){
                domHtml+=Api.createChatItem(messageArr[i]);
            }
            Api.isMeassageTips(messageArr.length);
            $('#message_chat_content').html(domHtml);
            Api.toChatEnd();

        },
        //判断是否显示快捷提示
        isMeassageTips:function (len) {
            if(len > 0){
                $('#chat_kuaijie').hide();
            }else{
                $('#chat_kuaijie').show();
            }
        },

        //toEnd滚动最新回答
        toChatEnd:function () {
            var scrollHeight = $('#chat_content_wrapper').prop("scrollHeight");
            $('#chat_content_wrapper').scrollTop(scrollHeight,200);
        },

        //发送消息请求接口
        sendMessage:function (message) {
            if(message == ''){
                return;
            }
            Api.setInputStatus(true)
            Api.addMessageDom(message,0)
            let  apikey=$.zui.store.get('chat_key');
            apikey = apikey ? apikey :'';
            var postData={
                'message':message,
                'contents':contentsArr,
                'apikey':apikey
            }
            var  loadIndex =layer.msg('正在组织语言，请稍等片刻...', {
                icon: 16,
                shade: 0.4,
                time: false //取消自动关闭
            });
            Api.ajax(
                {'url':siteConfig.send_message_url,loading:false,'data':postData},
                function (ret) {
                    if(ret.stream == true){
                        Api.eventsourceApi(message,loadIndex);
                    }else{
                        Api.addMessageDom(ret.reply_message,1);
                        Api.setInputStatus(false)
                        layer.close(loadIndex)
                    }
                    return false;
                },function (data, ret) {
                    layer.close(loadIndex);
                    Api.setInputStatus(false)
                    var chatItemId = 'item_'+Api.createId(); //会话单行domid
                    if(typeof data.error_code != 'undefined'){
                        Api.errorCode(data.error_code,ret.msg,chatItemId)
                    }else{
                        Api.errorCode('no',ret.msg,chatItemId)
                    }
                    return false;
                }
            )
        },
        //输出流
        eventsourceApi:function (MassageTxt,loadIndex) {
            var es = new EventSource(siteConfig.eventsource_url);
            var alltext = "";
            var chatItemId = 'item_'+Api.createId(); //会话单行domid
            var isStartText = true, //是否第一次接收数据
                isEndText = false,//是数据发送完成
                timeIndex=null, //定时器索引
                isError=false;//是否错误
            es.onerror = function (event) {
                Api.setInputStatus(false)
                es.close();
                return;
            }

            es.onmessage = function (event) {
                if (event.data == "end") {
                    es.close();
                    isEndText= true;
                    if(!isError){
                        contentsArr.push([MassageTxt, alltext]);
                        contentsArr = contentsArr.slice(-5); //只保留最近5次对话作为上下文，以免超过最大tokens限制
                    }
                } else {
                    var jsonDta=event.data;
                    if (jsonDta !== '') {
                        let pushData = JSON.parse(jsonDta);
                        if(typeof pushData.error_code != 'undefined'){
                            isError=true;
                            Api.errorCode(pushData.errcode,pushData.msg,chatItemId)
                        }else{
                            let lineTxt=pushData.msg;
                            alltext +=lineTxt;
                        }

                    }
                }
                if(isStartText){
                    layer.close(loadIndex)
                    if(isError == false){
                        let str_ = ''; //实现比较丝滑的显示
                        let i = 0;//实现比较丝滑的显示
                        timeIndex=setInterval(function () {
                            let newalltext = alltext;
                            let curr_text='';
                            let islastletter = false; //数学公式
                            //有时服务器错误地返回\\n作为换行符，尤其是包含上下文的提问时，这行代码可以处理一下。
                            if (newalltext.split("\n\n").length == newalltext.split("\n").length) {
                                newalltext = newalltext.replace(/\\n/g, '\n');
                            }
                            if (str_.length < newalltext.length) {
                                str_ += newalltext[i++];
                                curr_text = str_ +'<i class="chat-cursor"></i>';
                                if ((str_.split("```").length % 2) == 0){
                                    curr_text += "\n```\n";
                                }
                            } else {
                                if (isEndText) {
                                    clearInterval(timeIndex);
                                    curr_text = str_ ;
                                    islastletter = true;
                                }
                            }
                            let wordText = mdHtml.render(curr_text); //转换内容
                            Api.updateStreamChatItem(wordText,chatItemId);
                            if (islastletter){
                                Api.setChatMessage({'type':1,message:wordText})
                                let mach=document.getElementById(chatItemId);
                                MathJax.Hub.Queue(["Typeset", MathJax.Hub,mach]);
                                Api.setInputStatus(false)
                            }
                        },35)
                    }
                    isStartText=false;

                }
            }
        },
        //添加单个dom
        addMessageDom:function (message,type =0) {
            Api.isMeassageTips(1);
            var messageItem={'type':type,'message':message}
            Api.setChatMessage(messageItem);
            var itemHtml=Api.createChatItem(messageItem);
            $('#message_chat_content').append(itemHtml);
            Api.toChatEnd();
        },

        //创建dom
        createChatItem:function (messageItem) {
            var className=messageItem.type == 1 ?'chat-this':'';
            var avatar=messageItem.type == 1 ? siteConfig.chatgpt_avatar: siteConfig.user_avatar;
            var html='<div class="list-group-item '+className+'">\n' +
                '                    <div class="chat-list-item">\n' +
                '                        <div class="chat-img">\n' +
                '                            <img src="'+avatar+'" class="chat-avatar" alt="">\n' +
                '                        </div>\n' +
                '                        <div class="chat-body ">\n' +
                '                            <div class="chat-message-text">'+messageItem.message+'</div>\n' +
                '                        </div>\n' +
                '                    </div>\n' +
                '</div>';
            return html;
        },
        //创建stream输出流dmo
        updateStreamChatItem:function (wordText,dmoId) {

            if($("#"+dmoId).length > 0){
                $("#"+dmoId).html(wordText);
            }else{
                var html='<div class="list-group-item chat-this">\n' +
                    '                    <div class="chat-list-item">\n' +
                    '                        <div class="chat-img">\n' +
                    '                            <img src="'+siteConfig.chatgpt_avatar+'" class="chat-avatar" alt="">\n' +
                    '                        </div>\n' +
                    '                        <div class="chat-body ">\n' +
                    '                            <div class="chat-message-text"  id="'+dmoId+'">'+wordText+'</div>\n' +
                    '                        </div>\n' +
                    '                    </div>\n' +
                    '</div>';
                $('#message_chat_content').append(html);
            }
            Api.toChatEnd();
        },
        updateKeyStatus:function () {
          let  key=$.zui.store.get('chat_key');
          if(key){
              $('#chat_keystatus').html('<small class="label label-badge pull-right label-danger" >已设置</small>')
          }else {
              $('#chat_keystatus').html('<small class="label label-badge pull-right " >未设置</small>')
          }
        },
        events: {
            //请求成功的回调
            onAjaxSuccess: function (ret, onAjaxSuccess) {
                var data = typeof ret.data !== 'undefined' ? ret.data : null;
                var msg = typeof ret.msg !== 'undefined' && ret.msg ? ret.msg :'未知错误';

                if (typeof onAjaxSuccess === 'function') {
                    var result = onAjaxSuccess.call(this, data, ret);
                    if (result === false)
                        return;
                }
                Api.msg(msg)
            },
            //请求错误的回调
            onAjaxError: function (ret, onAjaxError) {
                var data = typeof ret.data !== 'undefined' ? ret.data : null;
                if (typeof onAjaxError === 'function') {
                    var result = onAjaxError.call(this, data, ret);
                    if (result === false) {
                        return;
                    }
                }
                Api.msg(ret.msg)

            },
            //服务器响应数据后
            onAjaxResponse: function (response) {
                try {
                    var ret = typeof response === 'object' ? response : JSON.parse(response);
                    if (!ret.hasOwnProperty('code')) {
                        $.extend(ret, {code: -2, msg: response, data: null});
                    }
                } catch (e) {
                    var ret = {code: -1, msg: e.message, data: null};
                }
                return ret;
            }
        },
    }
    //读取历史消息
    Api.initChatMessage();
    Api.updateKeyStatus()
    //检测环境
    if(Api.isIE()){
        alert('不支持ie浏览器,请更换浏览器')
    }else if($.zui.store.enable === false){
        alert('不支持存储,请更换浏览器')
    }


    /*导航点击对应操作*/
    $('.main-sidebar').on('click','li',function () {
        var action=$(this).attr('data-action');
        switch (action){
            case 'delchat':
                Api.delChatMessage();
                Api.msg('历史消息记录已清除！')
                break;
            case 'setkey':
                let  key=$.zui.store.get('chat_key');
                key = key ? key :'';
                layer.prompt(
                    {
                        title: '输入chatgpt的key，并确认',
                        formType: 0,
                        value:key,
                        btn: ['确认', '清空key', '取消'],
                        btn2: function(index, layero){
                            $.zui.store.remove('chat_key')
                            Api.msg('清空key成功')
                            Api.updateKeyStatus()
                        }

                     }, function(value, index){
                        if($.zui.store.set('chat_key',value)){
                            Api.msg('设置成功')
                            Api.updateKeyStatus()
                            layer.close(index);
                        }else{
                            Api.msg('设置失败请重试')
                        }

                });
                break;
        }
    });

    /*点击快捷用语*/
    $('.icon-block').on('click','li',function () {
        var message=$(this).text().trim();
        Api.sendMessage(message);
    })
    /*发送消息*/
    $('#sendMessage_btn').on('click',function () {
        var message=$('#sendMessage_val').val().trim();
        if(message == ''){
            Api.msg('消息不能为空!');
            return false;
        }
        Api.sendMessage(message);
        $('#sendMessage_val').val('');
    })
    /*监听回车键*/
    $("#sendMessage_val").on('keydown', function (event) {

        if (event.keyCode == 13) {
            var message=$('#sendMessage_val').val().trim();
            if(message == ''){
                Api.msg('消息不能为空!');
                return false;
            }
            Api.sendMessage(message);
            $('#sendMessage_val').val('');
            return false;
        }
    });
    /*复制code*/
    $('.chat-content').on('click','.chat-btn-copy',function () {
        Api.copyToClipboard($(this).closest('code').clone().children('button').remove().end().text());
        Api.msg("复制完成！");
    })

    /*点击打开侧边栏*/
    $('.sidebar-toggle').on('click',function () {
        if($("body").hasClass("sidebar-open")){
            $("body").removeClass('sidebar-open');
        }else{
            $("body").addClass('sidebar-open');
        }
    })
})